TOOL.Category = "Construction"
TOOL.Name = "Freezer"
TOOL.Command = nil
TOOL.ConfigName = ""

//Default values
TOOL.ClientConVar["primary_radius"] = 128
TOOL.ClientConVar["secondary_radius"] = 128
TOOL.ClientConVar["physgun"] = 0
TOOL.ClientConVar["contraption"] = 0
TOOL.ClientConVar["mild"] = 0

//Add language descriptions
if ( CLIENT ) then
language.Add( 'Tool_freezer_name', 'Freeze Tool' )
language.Add( 'Tool_freezer_desc', 'Freezes or unfreezes objects in a certain radius' )
language.Add( 'Tool_freezer_0', 'Left-Click: Freeze  Right-Click: Unfreeze  Reload: Shield' )
end

//Make sure clients get custom materials
if (SERVER) then
resource.AddFile("materials/refract_ring.vtf")
resource.AddFile("materials/refract_ring.vmt")
end


//Left-click function
function TOOL:LeftClick(trace)

//This is how we freeze things
local function Freeze(stuff, ply, mild, physgun)

if (CLIENT) then return end //Clients don't need to know about this

	//Ragdoll & Jeep freezing part
	if stuff:GetClass() == "prop_ragdoll" || stuff:GetClass() == "prop_vehicle_jeep" then
	for boneindex=1, stuff:GetPhysicsObjectCount() do
		local boneobject = stuff:GetPhysicsObjectNum(boneindex)
		if boneobject then
			if mild == 1 then boneobject:Sleep() end
			if mild == 0 then boneobject:EnableMotion(false) end
		end
	end
	end

	//Get physics object
	local phys = stuff:GetPhysicsObject()

	//Freeze your own props if not admin
	if !ply:IsAdmin() && !ply:IsSuperAdmin() && phys:GetOwner(ply) then
	if mild == 1 then phys:Sleep() end
	if mild == 0 then phys:EnableMotion(false) end
	end

	//Freeze everything if an admin
	if ply:IsAdmin() || ply:IsSuperAdmin() then
	if mild == 1 then phys:Sleep() end
	if mild == 0 then phys:EnableMotion(false) end
	end

	//Add to physgun unfreeze list - unused
	if physgun == 1 && mild == 0 then
	ply:AddFrozenPhysicsObject(stuff, phys)
	end

end

//Contraption mode - Freeze all attached props
if self:GetClientNumber("contraption") == 1 then
if trace.HitNonWorld && trace.Entity && trace.Entity:IsValid() then
if (SERVER) then

	//Get all attached entities
	local AttachedEnts = constraint.GetAllConstrainedEntities(trace.Entity) or {}
	AttachedEnts[trace.Entity:EntIndex()] = trace.Entity //Don't forget the original entity

	//Cycle through ents
	for _, stuff in pairs(AttachedEnts) do
		if stuff && stuff:IsValid() && stuff:GetPhysicsObject():IsValid() && !stuff:IsPlayer() then

		//Freeze
		Freeze(stuff, self:GetOwner(), self:GetClientNumber("mild"), self:GetClientNumber("physgun"))

		//Effects
		if stuff:GetClass() != "prop_ragdoll" then
		local sfx = EffectData()
		sfx:SetEntity(stuff)
		util.Effect("freezer_prop_freeze", sfx, true, true)
		end

		end
	end
end
end
end

//Spherical method - Freeze all props in radius
if self:GetClientNumber("contraption") == 0 then

if (SERVER) then

local freeze = ents.FindInSphere(trace.HitPos, self:GetClientNumber("primary_radius"))
	for _, stuff in pairs(freeze) do
		if stuff && stuff:IsValid() && stuff:GetPhysicsObject():IsValid() && !stuff:IsPlayer() then

		//Freeze
		Freeze(stuff, self:GetOwner(), self:GetClientNumber("mild"), self:GetClientNumber("physgun"))

		end
	end

end //End Server part

//Effects
local sfx = EffectData()
sfx:SetOrigin(trace.HitPos)
sfx:SetScale(self:GetClientNumber("primary_radius"))
util.Effect("freezer_shockwave",sfx)

end

return true //Shoot the laser

end


//Right-click function
function TOOL:RightClick(trace)

//This is how we unfreeze things
local function Unfreeze(stuff, ply, mild)

if (CLIENT) then return end //Clients don't need to know about this

	//Ragdoll & Jeep unfreezing part
	if stuff:GetClass() == "prop_ragdoll" || stuff:GetClass() == "prop_vehicle_jeep" then
	for boneindex=1, stuff:GetPhysicsObjectCount() do
		local boneobject = stuff:GetPhysicsObjectNum(boneindex)
		if boneobject then
			if mild == 1 then boneobject:Wake() end
			if mild == 0 then boneobject:EnableMotion(true) boneobject:Wake() end
		end
	end
	end

	//Get physics object
	local phys = stuff:GetPhysicsObject()

	//Unfreeze your own props if not admin
	if !ply:IsAdmin() && !ply:IsSuperAdmin() && phys:GetOwner(ply) then
	if mild == 1 then phys:Wake() end
	if mild == 0 then phys:EnableMotion(true) phys:Wake() end
	end

	//Unfreeze everything if an admin
	if ply:IsAdmin() || ply:IsSuperAdmin() then
	if mild == 1 then phys:Wake() end
	if mild == 0 then phys:EnableMotion(true) phys:Wake() end
	end

end

//Contraption mode - Unfreeze all attached props
if self:GetClientNumber("contraption") == 1 then
if trace.HitNonWorld && trace.Entity && trace.Entity:IsValid() then
if (SERVER) then

	//Get all attached entities
	local AttachedEnts = constraint.GetAllConstrainedEntities(trace.Entity) or {}
	AttachedEnts[trace.Entity:EntIndex()] = trace.Entity //Don't forget the original entity

	//Cycle through ents
	for _, stuff in pairs(AttachedEnts) do
		if stuff && stuff:IsValid() && stuff:GetPhysicsObject():IsValid() && !stuff:IsPlayer() then

		//Unfreeze
		Unfreeze(stuff, self:GetOwner(), self:GetClientNumber("mild"))

		//Effects
		if stuff:GetClass() != "prop_ragdoll" then
		local sfx = EffectData()
		sfx:SetEntity(stuff)
		util.Effect("freezer_prop_unfreeze", sfx, true, true)
		end

		end
	end
end
end
end

//Spherical method - Unfreeze all props in radius
if self:GetClientNumber("contraption") == 0 then

if (SERVER) then

local unfreeze = ents.FindInSphere(trace.HitPos, self:GetClientNumber("secondary_radius"))
	for _, stuff in pairs(unfreeze) do
		if stuff && stuff:IsValid() && stuff:GetPhysicsObject():IsValid() && !stuff:IsPlayer() then

		//Unfreeze
		Unfreeze(stuff, self:GetOwner(), self:GetClientNumber("mild"))

		end
	end

end //End Server part

//Effects
local sfx = EffectData()
sfx:SetOrigin(trace.HitPos)
sfx:SetScale(self:GetClientNumber("secondary_radius"))
util.Effect("freezer_shockwave",sfx)
util.ScreenShake( trace.HitPos, 1, 255, 0.5, self:GetClientNumber("secondary_radius") * 3 )

end

return true //Shoot the laser

end


//Reload function
function TOOL:Reload()

//Draw effects first
local sfx = EffectData()
sfx:SetOrigin(self:GetOwner():GetPos())
sfx:SetEntity(self:GetOwner())
util.Effect("freezer_shield",sfx)

if !(SERVER) then return end //Clients don't need to know about anything below this

//This is how we freeze things
local function Freeze(stuff, ply, mild, physgun)

	//Ragdoll & Jeep freezing part
	if stuff:GetClass() == "prop_ragdoll" || stuff:GetClass() == "prop_vehicle_jeep" then
	for boneindex=1, stuff:GetPhysicsObjectCount() do
		local boneobject = stuff:GetPhysicsObjectNum(boneindex)
		if boneobject then
			if mild == 1 then boneobject:Sleep() end
			if mild == 0 then boneobject:EnableMotion(false) end
		end
	end
	end

	//Get physics object
	local phys = stuff:GetPhysicsObject()

	//Freeze your own props if not admin
	if !ply:IsAdmin() && !ply:IsSuperAdmin() && phys:GetOwner(ply) then
	if mild == 1 then phys:Sleep() end
	if mild == 0 then phys:EnableMotion(false) end
	end

	//Freeze everything if an admin
	if ply:IsAdmin() || ply:IsSuperAdmin() then
	if mild == 1 then phys:Sleep() end
	if mild == 0 then phys:EnableMotion(false) end
	end

	//Add to physgun unfreeze list - unused
	if physgun == 1 && mild == 0 then
	ply:AddFrozenPhysicsObject(stuff, phys)
	end

end

//Find props in radius of the player
local shield = ents.FindInSphere(self:GetOwner():GetPos(), 512)
	for _, stuff in pairs(shield) do
		if stuff && stuff:IsValid() && stuff:GetPhysicsObject():IsValid() && !stuff:IsPlayer() then

		//Freeze
		Freeze(stuff, self:GetOwner(), self:GetClientNumber("mild"), self:GetClientNumber("physgun"))

		end
	end

return false //Don't shoot the laser

end


//Build Tool Menu
function TOOL.BuildCPanel(panel)
panel:AddControl( "Header", { Text = "#Tool_freezer_name", Description = "#Tool_freezer_desc" } )
panel:AddControl( "Slider", { Label = "Freeze radius", Type = "Integer", Min = "32", Max = "512", Command ="freezer_primary_radius" } )
panel:AddControl( "Slider", { Label = "Unfreeze radius", Type = "Integer", Min = "32", Max = "512", Command = "freezer_secondary_radius" } )
panel:AddControl( "CheckBox", { Label = "Add to Physgun unfreeze list", Description = "Allow props to be unfrozen by Physgun's Reload function", Command = "freezer_physgun" } )
panel:AddControl( "CheckBox", { Label = "Contraption mode", Description = "Toggle freezing everything in the area or just attached props", Command = "freezer_contraption" } )
panel:AddControl( "CheckBox", { Label = "Mild freezing", Description = "Props will unfreeze if touched", Command = "freezer_mild" } )
end